<?php

namespace app\msgapi\service;

use app\msgapi\model\{CueventLog, CustomerAdd, System};
use think\facade\{Cache, Db, Log};
error_reporting(E_ERROR | E_PARSE);
class HscallbackService
{

    /**通讯录回调
     * @return \think\response\Json|void
     * @throws \Throwable
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getContactEvent()
    {
        $xml = file_get_contents("php://input");
//        file_put_contents('../runtime/msgapi/log/202112/'.'test.log',$xml);
        include '../extend/weworkapi/callback/WXBizMsgCrypt.php';
        $sys_config = System::select()->column('val','name');
        if (!isset($sys_config['contacts_config'])) {
            Log::write('通讯录回调配置错误,请检查.','error');
            return error_json('通讯录回调配置错误,请检查.');
        }
//        Log::write(json_encode($sys_config['contacts_config'],256),'info');
        $corpInfo = HscorpInfoService::getCorpInfo(env('wework.corpid'),true); //获取企业密钥信息
        if(!isset($corpInfo['corp_info'])){
            Log::write('企业信息错误,请检查配置或缓存.','error');
            return error_json('企业信息错误,请检查配置或缓存.');
        }
//        Log::write(json_encode($corpInfo['corp_info'],256),'info');
        $token = $sys_config['contacts_config']['token'];
        $encodingAesKey =$sys_config['contacts_config']['encodingaeskey'];
        $cropid = $corpInfo['corp_info']['corpid'];
        $wxcpt = new \WXBizMsgCrypt($token, $encodingAesKey, $cropid);
        $msg_signature = input('msg_signature');
        $timestamp = input('timestamp');
        $nonce = input('nonce');
        $get_str = input('echostr');
        $Sechostr = '';
        //验证URL有效性。首次验证即可，验证完毕后注释/删除此段
        if($get_str){
            $errcode = $wxcpt->VerifyURL($msg_signature, $timestamp, $nonce, $get_str, $Sechostr);
            if ($errcode == 0) {
                echo $Sechostr;
            } else {
                print('ERR:' . $errcode . '\n\n');
            }
            die;
        }

        $errcode = $wxcpt->DecryptMsg($msg_signature, $timestamp, $nonce, $xml, $Sechostr);
        if ($errcode == 0) {
            $data = $this->xmlToArray($Sechostr);
//            Log::write(json_encode($data),'info');
            //新增成员
            if (($data['MsgType'] == 'event') && ($data['Event'] == 'change_contact') && ($data['ChangeType'] == 'create_user')) {
                $res = HsorganizationService::add_user($data);
            }
            //更新成员
            if (($data['MsgType'] == 'event') && ($data['Event'] == 'change_contact') && ($data['ChangeType'] == 'update_user')) {
                $res = HsorganizationService::update_user($data);
            }
            //删除成员
            if (($data['MsgType'] == 'event') && ($data['Event'] == 'change_contact') && ($data['ChangeType'] == 'delete_user')) {
                $res = HsorganizationService::delete_user($data);
            }
            //新增部门
            if (($data['MsgType'] == 'event') && ($data['Event'] == 'change_contact') && ($data['ChangeType'] == 'create_party')) {
                $res = HsorganizationService::add_department($data);
            }
            //更新部门
            if (($data['MsgType'] == 'event') && ($data['Event'] == 'change_contact') && ($data['ChangeType'] == 'update_party')) {
                $res = HsorganizationService::update_department($data);
            }
            //删除部门
            if (($data['MsgType'] == 'event') && ($data['Event'] == 'change_contact') && ($data['ChangeType'] == 'delete_party')) {
                $res = HsorganizationService::delete_department($data);
            }
            if ($res) {
                abort(200);
            } else {
                print('ERR：SAVE FALSE,TRY AGAIN!');
            }

        }
    }

    /**客户信息\群组回调(部分事件)
     * @return \think\response\Json|void
     * @throws \Throwable
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getCustomerEvent()
    {
        $xml = file_get_contents("php://input");
//        file_put_contents('../runtime/msgapi/log/202112/'.'test.log',$xml);
        include '../extend/weworkapi/callback/WXBizMsgCrypt.php';

        $sys_config = System::select()->column('val','name');
        if (!isset($sys_config['client_config'])) {
            Log::write('客户回调配置错误,请检查.','error');
            return error_json('客户回调配置错误,请检查.');
        }
//        Log::write(json_encode($sys_config['client_config'],256),'info');
        $corpInfo = HscorpInfoService::getCorpInfo(env('wework.corpid'),true); //获取企业密钥信息
        if(!isset($corpInfo['corp_info'])){
            Log::write('企业信息错误,请检查配置或缓存.','error');
            return error_json('企业信息错误,请检查配置或缓存.');
        }
//        Log::write(json_encode($corpInfo['corp_info'],256),'info');
        $token = $sys_config['client_config']['token'];
        $encodingAesKey =$sys_config['client_config']['encodingaeskey'];
        $cropid = $corpInfo['corp_info']['corpid'];
        $wxcpt = new \WXBizMsgCrypt($token, $encodingAesKey, $cropid);
        $msg_signature = input('msg_signature');
        $timestamp = input('timestamp');
        $nonce = input('nonce');
        $get_str = input('echostr');
        $Sechostr = '';
        //验证URL有效性。首次验证即可，验证完毕后注释/删除此段
        if($get_str){
            $errcode = $wxcpt->VerifyURL($msg_signature, $timestamp, $nonce, $get_str, $Sechostr);
            if ($errcode == 0) {
                echo $Sechostr;
            } else {
                print('ERR:' . $errcode . '\n\n');
            }
            die;
        }

        $errcode = $wxcpt->DecryptMsg($msg_signature, $timestamp, $nonce, $xml, $Sechostr);
        if ($errcode == 0) {
            //处理数据
            $data = $this->xmlToArray($Sechostr);
//            $data = $this->xmlToArray($Sechostr);
//            Log::write(json_encode($data,256),'info');
            $event_log = new CueventLog();

            //排重
            if (!$event_log->where(['FromUserName' => $data['FromUserName'], 'CreateTime' => $data['CreateTime']])->count()) {
                //保存变更日志,主要用来客户回调和同步时排重
                $event_log->save($data);
                $customer_add = new CustomerAdd();

                //客户信息变更与员工对应关系调整
                //查询是否存在当前日期的记录，不存在则先添加一条记录
                $time = date('Ymd');
                if (!$customer_add->where(['query_time' => $time])->count()) {
                    $customer_add->insert(['query_time' => $time]);
                }

                //外部联系人免验证添加成员事件 || 添加企业客户事件 || 编辑客户事件
                if (($data['MsgType'] === 'event') && ($data['Event'] === 'change_external_contact') && (($data['ChangeType'] == 'add_external_contact') || ($data['ChangeType'] == 'add_half_external_contact') || ($data['ChangeType'] == 'edit_external_contact'))) {
                    Db::startTrans();
                    try {
                        Db::table('hs_customer_add')->where('query_time','=', $time)->inc('add_number',1)->update();
                        HuihuaCustService::add_customer($data['UserID'],$data['ExternalUserID']);
                        Db::commit();
                    }catch (\Exception $e){
                        Db::rollback();
                        Log::write('[回调]客户回调操作失败,数据已回滚,错误原因:'.$e->getMessage().'行号:'.$e->getLine());
                    }
                }
                //删除企业客户事件 || 删除跟进成员事件
                if (($data['MsgType'] === 'event') &&
                    ($data['Event'] === 'change_external_contact') &&
                    (($data['ChangeType'] == 'del_external_contact') || ($data['ChangeType'] == 'del_follow_user'))
                ) {
                    if(HuihuaCustService::detele_cust($data['UserID'],$data['ExternalUserID'],$data['ChangeType'])){
                        Db::table('hs_customer_add')->where('query_time','=', $time)->inc('delete_number',1)->update(); //更新客户统计
                    }
                }

                //客户接替失败事件
                if (($data['MsgType'] === 'event') && ($data['Event'] === 'change_external_contact') && ($data['ChangeType'] == 'transfer_fail')) {
//                    $res = true;//todo 需要再进一步沟通接替失败该怎么做
                }
                //客户群创建事件
                if (($data['MsgType'] === 'event') && ($data['Event'] === 'change_external_chat') && ($data['ChangeType']=='create')) {
                    HuihuaGroupChatService::getGroupDetail($data['ChatId']);
                }
                //客户群解散事件
                if (($data['MsgType'] === 'event') && ($data['Event'] === 'change_external_chat') && ($data['ChangeType']=='dismiss')) {
                    HuihuaGroupChatService::dismissGroup($data['ChatId']);
                }
                //客户群入群事件
                if (($data['MsgType'] === 'event') && ($data['Event'] === 'change_external_chat') && ($data['ChangeType']=='update')) {
                    //todo 暂时不需要
                }
                abort(200);
            }
        } else {
            print("ERR: " . $errcode . "\n\n");
        }
    }

    /**会话消息拉取回调
     * @return \think\response\Json|void
     * @throws \Throwable
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function callbackPullMsg()
    {
        $xml = file_get_contents("php://input");
//        file_put_contents('../runtime/msgapi/log/202112/'.'test.log',$xml);
        include '../extend/weworkapi/callback/WXBizMsgCrypt.php';

        $sys_config = System::select()->column('val','name');
        if (!isset($sys_config['pullmsg_config'])) {
            Log::write('会话拉取回调配置错误,请检查.','error');
            return error_json('会话拉取回调配置错误,请检查.');
        }
//        Log::write(json_encode($sys_config['client_config'],256),'info');
        $corpInfo = HscorpInfoService::getCorpInfo(env('wework.corpid'),true); //获取企业密钥信息
        if(!isset($corpInfo['corp_info'])){
            Log::write('企业信息错误,请检查配置或缓存.','error');
            return error_json('企业信息错误,请检查配置或缓存.');
        }
//        Log::write(json_encode($corpInfo['corp_info'],256),'info');
        $token = $sys_config['pullmsg_config']['token'];
        $encodingAesKey =$sys_config['pullmsg_config']['encodingaeskey'];
        $cropid = $corpInfo['corp_info']['corpid'];
        $wxcpt = new \WXBizMsgCrypt($token, $encodingAesKey, $cropid);
        $msg_signature = input('msg_signature');
        $timestamp = input('timestamp');
        $nonce = input('nonce');
        $get_str = input('echostr');
        $Sechostr = '';
        //验证URL有效性。首次验证即可，验证完毕后注释/删除此段
        if($get_str){
            $errcode = $wxcpt->VerifyURL($msg_signature, $timestamp, $nonce, $get_str, $Sechostr);
            if ($errcode == 0) {
                echo $Sechostr;
            } else {
                print('ERR:' . $errcode . '\n\n');
            }
            die;
        }

        $errcode = $wxcpt->DecryptMsg($msg_signature, $timestamp, $nonce, $xml, $Sechostr);
        if ($errcode == 0) {
            //处理数据
            $data = $this->xmlToArray($Sechostr);
//            Log::write(json_encode($data,256),'info');
            if (($data['MsgType'] === 'event') && ($data['Event'] === 'msgaudit_notify')) {
                if (Cache::get('is_pullmsglst') !== true || !Cache::get('is_pullmsglst')) {
                    Log::write('[回调]会话消息拉取任务开始', 'info');
                    exec('php ' . app()->getRootPath() . '\think pullmsglst', $a, $b);
                    Log::write('[回调]会话消息拉取任务结束', 'info');
                } else {
                    Log::write('同步程序已在执行中,请等待执行完成.', 'error');
                    return error_json('同步程序已在执行中,请等待执行完成');
                }
            }
            abort(200);
        }else{
            print("ERR: " . $errcode . "\n\n");
        }
    }
    function xmlToArray($xml)
    {
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $values;
    }


}